﻿#include "stdafx.h"

namespace DuiLib {
//CDateTimeUI::m_nDTUpdateFlag
#define DT_NONE   0
#define DT_UPDATE 1
#define DT_DELETE 2
#define DT_KEEP   3

class CDateTimeWnd : public CWindowWnd
{
public:
    CDateTimeWnd();

    void Init(CDateTimeUI *pOwner);
    RECT CalPos();

    LPCTSTR GetWindowClassName() const;
    LPCTSTR GetSuperClassName() const;
    void OnFinalMessage(HWND hWnd);

    LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
    LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
    //LRESULT OnEditChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

protected:
    CDateTimeUI *m_pOwner;
    HBRUSH m_hBkBrush;
    bool m_bInit;
};

CDateTimeWnd::CDateTimeWnd() : m_pOwner(NULL), m_hBkBrush(NULL), m_bInit(false)
{
}

void CDateTimeWnd::Init(CDateTimeUI *pOwner)
{
    m_pOwner = pOwner;
    m_pOwner->m_nDTUpdateFlag = DT_NONE;

    if (m_hWnd == NULL)
    {
        RECT rcPos = CalPos();
        UINT uStyle = WS_CHILD;
        Create(m_pOwner->GetManager()->GetPaintWindow(), NULL, uStyle, 0, rcPos);
        SetWindowFont(m_hWnd, m_pOwner->GetManager()->GetFontInfo(m_pOwner->GetFont())->hFont, TRUE);
    }

    if (m_pOwner->GetText().IsEmpty())
    { ::GetLocalTime(&m_pOwner->m_sysTime); }

    ::SendMessage(m_hWnd, DTM_SETSYSTEMTIME, 0, (LPARAM)&m_pOwner->m_sysTime);
    ::ShowWindow(m_hWnd, SW_SHOWNOACTIVATE);
    ::SetFocus(m_hWnd);

    m_bInit = true;
}

RECT CDateTimeWnd::CalPos()
{
    CDuiRect rcPos = m_pOwner->GetPos();

    CControlUI *pParent = m_pOwner;
    RECT rcParent;

    while (pParent = pParent->GetParent())
    {
        if (!pParent->IsVisible())
        {
            rcPos.left = rcPos.top = rcPos.right = rcPos.bottom = 0;
            break;
        }

        rcParent = pParent->GetClientPos();

        if (!::IntersectRect(&rcPos, &rcPos, &rcParent))
        {
            rcPos.left = rcPos.top = rcPos.right = rcPos.bottom = 0;
            break;
        }
    }

    return rcPos;
}

LPCTSTR CDateTimeWnd::GetWindowClassName() const
{
    return _T("DateTimeWnd");
}

LPCTSTR CDateTimeWnd::GetSuperClassName() const
{
    return DATETIMEPICK_CLASS;
}

void CDateTimeWnd::OnFinalMessage(HWND hWnd)
{
    // Clear reference and die
    if (m_hBkBrush != NULL) { ::DeleteObject(m_hBkBrush); }

    m_pOwner->GetManager()->RemoveNativeWindow(hWnd);
    m_pOwner->m_pWindow = NULL;
    delete this;
}

LRESULT CDateTimeWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LRESULT lRes = 0;
    BOOL bHandled = TRUE;

    if (uMsg == WM_CREATE)
    {
        m_pOwner->GetManager()->AddNativeWindow(m_pOwner, m_hWnd);
        bHandled = FALSE;
    }
    else if (uMsg == WM_KILLFOCUS)
    {
        lRes = OnKillFocus(uMsg, wParam, lParam, bHandled);
    }
    else if (uMsg == WM_KEYUP && (wParam == VK_DELETE || wParam == VK_BACK))
    {
        LRESULT lRes = ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);
        m_pOwner->m_nDTUpdateFlag = DT_DELETE;
        m_pOwner->UpdateText();
        PostMessage(WM_CLOSE);
        return lRes;
    }
    else if (uMsg == WM_KEYUP && wParam == VK_ESCAPE)
    {
        LRESULT lRes = ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);
        m_pOwner->m_nDTUpdateFlag = DT_KEEP;
        PostMessage(WM_CLOSE);
        return lRes;
    }
    //  else if( uMsg == OCM_COMMAND ) {
    //      if( GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE ) lRes = OnEditChanged(uMsg, wParam, lParam, bHandled);
    //      else if( GET_WM_COMMAND_CMD(wParam, lParam) == EN_UPDATE ) {
    //          RECT rcClient;
    //          ::GetClientRect(m_hWnd, &rcClient);
    //          ::InvalidateRect(m_hWnd, &rcClient, FALSE);
    //      }
    //  }
    //  else if( uMsg == WM_KEYDOWN && TCHAR(wParam) == VK_RETURN ) {
    //      m_pOwner->GetManager()->SendNotify(m_pOwner, DUI_MSGTYPE_RETURN);
    //  }
    //      else if( uMsg == OCM__BASE + WM_CTLCOLOREDIT  || uMsg == OCM__BASE + WM_CTLCOLORSTATIC ) {
    //          if( m_pOwner->GetNativeEditBkColor() == 0xFFFFFFFF ) return NULL;
    //          ::SetBkMode((HDC)wParam, TRANSPARENT);
    //          DWORD dwTextColor = m_pOwner->GetTextColor();
    //          ::SetTextColor((HDC)wParam, RGB(GetBValue(dwTextColor),GetGValue(dwTextColor),GetRValue(dwTextColor)));
    //          if( m_hBkBrush == NULL ) {
    //              DWORD clrColor = m_pOwner->GetNativeEditBkColor();
    //              m_hBkBrush = ::CreateSolidBrush(RGB(GetBValue(clrColor), GetGValue(clrColor), GetRValue(clrColor)));
    //          }
    //          return (LRESULT)m_hBkBrush;
    //      }
    else if (uMsg == WM_PAINT)
    {
        if (m_pOwner->GetManager()->IsLayered())
        {
            m_pOwner->GetManager()->AddNativeWindow(m_pOwner, m_hWnd);
        }

        bHandled = FALSE;
    }
    else { bHandled = FALSE; }

    if (!bHandled) { return CWindowWnd::HandleMessage(uMsg, wParam, lParam); }

    return lRes;
}

LRESULT CDateTimeWnd::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
    LRESULT lRes = ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);

    if (m_pOwner->m_nDTUpdateFlag == DT_NONE)
    {
        ::SendMessage(m_hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&m_pOwner->m_sysTime);
        m_pOwner->m_nDTUpdateFlag = DT_UPDATE;
        m_pOwner->UpdateText();
    }

    if ((HWND)wParam != m_pOwner->GetManager()->GetPaintWindow())
    {
        ::SendMessage(m_pOwner->GetManager()->GetPaintWindow(), WM_KILLFOCUS, wParam, lParam);
    }

    SendMessage(WM_CLOSE);
    return lRes;
}

// LRESULT CDateTimeWnd::OnEditChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// {
//  if( !m_bInit ) return 0;
//  if( m_pOwner == NULL ) return 0;
//  // Copy text back
//  int cchLen = ::GetWindowTextLength(m_hWnd) + 1;
//  LPTSTR pstr = static_cast<LPTSTR>(_alloca(cchLen * sizeof(TCHAR)));
//  ASSERT(pstr);
//  if( pstr == NULL ) return 0;
//  ::GetWindowText(m_hWnd, pstr, cchLen);
//  m_pOwner->m_sText = pstr;
//  m_pOwner->GetManager()->SendNotify(m_pOwner, DUI_MSGTYPE_TEXTCHANGED);
//  return 0;
// }

//////////////////////////////////////////////////////////////////////////
//
CDateTimeUI::CDateTimeUI()
{
    ::GetLocalTime(&m_sysTime);
    m_bReadOnly = false;
    m_pWindow = NULL;
    m_nDTUpdateFlag = DT_UPDATE;
    UpdateText();       // add by:daviyang35 初始化界面时显示时间
    m_nDTUpdateFlag = DT_NONE;
}

LPCTSTR CDateTimeUI::GetClass() const
{
    return DUI_CTR_DATETIME;
}

LPVOID CDateTimeUI::GetInterface(LPCTSTR pstrName)
{
    if (_tcscmp(pstrName, DUI_CTR_DATETIME) == 0) { return static_cast<CDateTimeUI *>(this); }

    return CLabelUI::GetInterface(pstrName);
}

UINT CDateTimeUI::GetControlFlags() const
{
    return UIFLAG_TABSTOP;
}

HWND CDateTimeUI::GetNativeWindow() const
{
    if (m_pWindow) { return m_pWindow->GetHWND(); }

    return NULL;
}

SYSTEMTIME &CDateTimeUI::GetTime()
{
    return m_sysTime;
}

void CDateTimeUI::SetTime(SYSTEMTIME *pst)
{
    m_sysTime = *pst;
    Invalidate();
}

void CDateTimeUI::SetReadOnly(bool bReadOnly)
{
    m_bReadOnly = bReadOnly;
    Invalidate();
}

bool CDateTimeUI::IsReadOnly() const
{
    return m_bReadOnly;
}

void CDateTimeUI::UpdateText()
{
    if (m_nDTUpdateFlag == DT_DELETE)
    { SetText(_T("")); }
    else if (m_nDTUpdateFlag == DT_UPDATE)
    {
        CDuiString sText;
        sText.SmallFormat(_T("%4d-%02d-%02d"),
                          m_sysTime.wYear, m_sysTime.wMonth, m_sysTime.wDay, m_sysTime.wHour, m_sysTime.wMinute);
        SetText(sText);
    }
}

void CDateTimeUI::SetPos(RECT rc, bool bNeedInvalidate)
{
    CControlUI::SetPos(rc, bNeedInvalidate);

    if (m_pWindow != NULL)
    {
        RECT rcPos = m_pWindow->CalPos();

        if (::IsRectEmpty(&rcPos)) { ::ShowWindow(m_pWindow->GetHWND(), SW_HIDE); }
        else
        {
            ::SetWindowPos(m_pWindow->GetHWND(), NULL, rcPos.left, rcPos.top, rcPos.right - rcPos.left,
                           rcPos.bottom - rcPos.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
        }
    }
}

void CDateTimeUI::Move(SIZE szOffset, bool bNeedInvalidate)
{
    CControlUI::Move(szOffset, bNeedInvalidate);

    if (m_pWindow != NULL)
    {
        RECT rcPos = m_pWindow->CalPos();

        if (::IsRectEmpty(&rcPos)) { ::ShowWindow(m_pWindow->GetHWND(), SW_HIDE); }
        else
        {
            ::SetWindowPos(m_pWindow->GetHWND(), NULL, rcPos.left, rcPos.top, rcPos.right - rcPos.left,
                           rcPos.bottom - rcPos.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
        }
    }
}

void CDateTimeUI::DoEvent(TEventUI &event)
{
    if (!IsMouseEnabled() && event.Type > UIEVENT__MOUSEBEGIN && event.Type < UIEVENT__MOUSEEND)
    {
        if (m_pParent != NULL) { m_pParent->DoEvent(event); }
        else { CLabelUI::DoEvent(event); }

        return;
    }

    if (event.Type == UIEVENT_SETCURSOR && IsEnabled())
    {
        ::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_IBEAM)));
        return;
    }

    if (event.Type == UIEVENT_WINDOWSIZE)
    {
        if (m_pWindow != NULL) { m_pManager->SetFocusNeeded(this); }
    }

    if (event.Type == UIEVENT_SCROLLWHEEL)
    {
        if (m_pWindow != NULL) { return; }
    }

    if (event.Type == UIEVENT_SETFOCUS && IsEnabled())
    {
        if (m_pWindow) { return; }

        m_pWindow = new CDateTimeWnd();
        ASSERT(m_pWindow);
        m_pWindow->Init(this);
        m_pWindow->ShowWindow();
    }

    if (event.Type == UIEVENT_KILLFOCUS && IsEnabled())
    {
        Invalidate();
    }

    if (event.Type == UIEVENT_BUTTONDOWN || event.Type == UIEVENT_LBUTTONDBLDOWN ||
        event.Type == UIEVENT_RBUTTONDOWN)
    {
        if (IsEnabled())
        {
            // 2018-05-28 原来代码在manager中捕获，在此释放。修改Capture机制后，由控件自己决定是否捕获
            // ReleaseCapture();

            if (IsFocused() && m_pWindow == NULL)
            {
                m_pWindow = new CDateTimeWnd();
                ASSERT(m_pWindow);
            }

            if (m_pWindow != NULL)
            {
                m_pWindow->Init(this);
                m_pWindow->ShowWindow();
            }
        }

        return;
    }

    if (event.Type == UIEVENT_MOUSEMOVE)
    {
        return;
    }

    if (event.Type == UIEVENT_BUTTONUP)
    {
        return;
    }

    if (event.Type == UIEVENT_CONTEXTMENU)
    {
        return;
    }

    CLabelUI::DoEvent(event);
}

SIZE CDateTimeUI::EstimateSize(SIZE szAvailable)
{
    CLabelUI::EstimateSize(szAvailable);
    m_cxyFixedLast.cx += 26;
    return m_cxyFixedLast;
}

void CDateTimeUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
{
    if (_tcscmp(pstrName, _T("dragenable")) == 0) { DUITRACE(_T("不支持属性:dragenable")); }
    else if (_tcscmp(pstrName, _T("dragimage")) == 0) { DUITRACE(_T("不支持属性:drageimage")); }
    else if (_tcscmp(pstrName, _T("dropenable")) == 0) { DUITRACE(_T("不支持属性:dropenable")); }
    else { CLabelUI::SetAttribute(pstrName, pstrValue); }
}

}
